package com.song.rabbitmq.springbootorderrabbitmqproducertopic.config;



import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 主题模式消息配置
 *
 *
 * 业务场景：
 * 在这个业务场景中，我们定义了一个主题交换机topic_order_exchange和三个队列："queue_new_order"、"queue_order_paid"、"queue_order_shipped"。
 * 每个队列都通过特定的routing key绑定到交换机。
 *
 * 当新订单创建时，消息会被发送到"queue_new_order"队列；
 * 当订单支付时，消息会被发送到"queue_order_paid"队列；
 * 当订单发货时，消息会被发送到"queue_order_shipped"队列。
 *
 * 这样，不同的服务可以监听特定的队列，根据订单的不同状态进行处理。
 *
 * # 匹配一个，  * 匹配多个
 */



@Configuration
public class TopicRabbitConfig {

    // 创建交换机
    @Bean
    TopicExchange orderTopicExchange() {
        return new TopicExchange("topic_order_exchange");
    }


    // 创建队列
    @Bean
    Queue queueNewOrder() {
        return new Queue("queue_order_new");
    }
    @Bean
    Queue queueOrderPaid() {
        return new Queue("queue_order_paid");
    }
    @Bean
    Queue queueOrderShipped() {
        return new Queue("queue_order_shipped");
    }
    @Bean
    Queue queueOrderTest() {
        return new Queue("queue_order_test");
    }



    // 绑定队列到交换机，并设置相应的routing key，来控制哪部分队列应该接收到消息
    @Bean
    Binding bindingNewOrder(Queue queueNewOrder, TopicExchange orderTopicExchange) {
        return BindingBuilder.bind(queueNewOrder).to(orderTopicExchange).with("order.new");
    }
    @Bean
    Binding bindingOrderPaid(Queue queueOrderPaid, TopicExchange orderTopicExchange) {
        return BindingBuilder.bind(queueOrderPaid).to(orderTopicExchange).with("order.paid");
    }
    @Bean
    Binding bindingOrderShipped(Queue queueOrderShipped, TopicExchange orderTopicExchange) {
        return BindingBuilder.bind(queueOrderShipped).to(orderTopicExchange).with("order.shipped");
    }

    // 如果routing key是order.test 这个队列也能收到，如果是 order.paid，那这个队列和queue_order_paidu队列都能收到，
    @Bean
    Binding bindingTestOrder(Queue queueOrderTest, TopicExchange orderTopicExchange) {
        return BindingBuilder.bind(queueOrderTest).to(orderTopicExchange).with("order.#");
    }



}




/*
    主题交换（Topic Exchange）在复杂的业务场景中非常有用，尤其是当你需要根据多个标准来路由消息时。以下是一些实际的复杂业务场景，其中主题交换模式会非常适用：

    1. 多重条件过滤：
    假设你有一个电商平台，需要根据产品类型、地区、和活动来发送消息。你可以有如下的routing keys：
    - product.electronics.newyork.flashsale
    - product.clothing.california.clearance
    在这种情况下，消费者可以订阅所有电子产品的消息，无论地区和活动类型（product.electronics.#），或者只订阅加州所有清仓活动的消息（product.#.california.clearance）。

    2. 动态路由：
    在一个日志系统中，你可能想根据日志的严重性和来源来路由消息。例如：
    - log.info.serviceA
    - log.error.serviceB
    你可以设置消费者来监听特定服务的所有日志（log.#.serviceA），或者监听所有错误日志（log.error.#）。

    3. 灵活的主题订阅：
    在股票市场应用中，你可能需要根据股票代码和市场更新类型来发送不同的消息：
    - stock.NASDAQ.AAPL
    - stock.NYSE.GOOG
    消费者可以订阅特定市场的所有股票更新（stock.NASDAQ.#），或者订阅所有市场中特定股票的更新（stock.#.AAPL）。

    4. 用户行为跟踪：
    如果你正在构建一个需要跟踪用户行为的系统，比如点击、购买等，你的routing keys可能如下：
    - user.click.pageA
    - user.purchase.productB
    消费者可以订阅所有用户的购买行为（user.purchase.#），或者特定页面的所有用户行为（user.#.pageA）。

    在这些场景中，主题交换提供了强大的灵活性，允许消费者根据模式（而不是完全匹配的routing key）来订阅消息。这种灵活性在直接交换中是不可用的，因为直接交换要求routing key完全匹配。主题交换使得系统能够更好地扩展，并且可以在不修改交换机或生产者的情况下，通过添加新的队列和绑定来适应新的业务需求。

*/
